package net.ibizsys.psstudio.ms.springboot.api.srv.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import lombok.Data;

@Component
public class MqttUtils {

	public static String HOST;

	public static Map<String, MqttClient> clientmap = new HashMap<String, MqttClient>();

	private static final Log log = LogFactory.getLog(MqttUtils.class);

	@Value("${mqtt.host:''}")
	public void setHost(String host) {
		HOST = host;
	}

	public static MqttClient Connect(String clientid) throws MqttException {

		MqttClient client = clientmap.get(clientid);

		if (client == null) {
			// host为主机名，clientid即连接MQTT的客户端ID，一般以唯一标识符表示，MemoryPersistence设置clientid的保存形式，默认为以内存保存
			client = new MqttClient(HOST, clientid, new MemoryPersistence());
			// MQTT的连接设置
			MqttConnectOptions options = new MqttConnectOptions();
			// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，这里设置为true表示每次连接到服务器都以新的身份连接
			options.setCleanSession(true);
			// 设置连接的用户名
			// options.setUserName(userName);
			// // 设置连接的密码
			// options.setPassword(passWord.toCharArray());
			// 设置超时时间 单位为秒
			options.setConnectionTimeout(10);
			// 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息 判断客户端是否在线，但这个方法并没有重连的机制
			options.setKeepAliveInterval(20);
			// 设置回调
			client.setCallback(new MqttCallback() {

				public void connectionLost(Throwable cause) {
					// 连接丢失后，一般在这里面进行重连
					System.out.println("连接断开，可以做重连");
				}

				public void deliveryComplete(IMqttDeliveryToken token) {
					// System.out.println("deliveryComplete---------" + token.isComplete());
				}

				public void messageArrived(String topic, MqttMessage message) throws Exception {
					// subscribe后得到的消息会执行到这里面
					// System.out.println("接收消息的主题 : " + topic);
					// System.out.println("接收消息的质量Qos : " + message.getQos());

					// String msg = new String(message.getPayload());
					// System.out.println(">>>>>>>>>>>>>>>>>>>" + msg);
				}

			});

			// MqttTopic topic = client.getTopic(TOPIC);
			// setWill方法，如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
			// options.setWill(topic, "close".getBytes(), 2, true);

			client.connect(options);
			log.info(String.format("客户端连接，id[%1$s]", clientid));
			clientmap.put(clientid, client);
		} else if (!client.isConnected()) {
			client.reconnect();
			log.info(String.format("客户端重连，id[%1$s]", clientid));
		}
		return client;

	}

	// 消息发布（默认qos）
	public static void Publish(String topic, String content, MqttClient client)
			throws MqttPersistenceException, MqttException {
		int qos = 2;
		Publish(topic, content, client, qos);
	}

	// 消息发布
	public static void Publish(String topic, String content, MqttClient client, int qos)
			throws MqttPersistenceException, MqttException {
		MqttMessage message = new MqttMessage(content.getBytes());
		message.setQos(qos);
		client.publish(topic, message);
	}

	// 多主题消息发布
	public static void PublishTotopics(List<String> topics, String content, MqttClient client)
			throws MqttPersistenceException, MqttException {
		int qos = 2;
		PublishTotopics(topics, content, client, qos);
	}

	// 多主题消息发布
	public static void PublishTotopics(List<String> topics, String content, MqttClient client, int qos)
			throws MqttPersistenceException, MqttException {
		MqttMessage message = new MqttMessage(content.getBytes());
		message.setQos(qos);

		for (String topic : topics) {
			client.publish(topic, message);
		}
	}

	// 客户端注销
	public static void Disconnect(MqttClient client) throws MqttPersistenceException, MqttException {
		if (client != null) {
			if (client.isConnected())
				client.disconnect();
			client.close();
		}

		client = null;
	}

	@Data
	public class MQTTMSG {
		String clientid;
		String topic;
		String content;

	}
}